package Kernel;

import java.lang.Thread.State;
import java.util.*;
import LivenessCheckOfFreeChoiceNet.FreeChoiceNet;;

public class Net {
	List<Place> PlaceSet = Place.PlaceSet;
	List<Transition> TransitionSet = Transition.TransitionSet;
	List<Arc_P2T> ArcP2TSet = new ArrayList<Arc_P2T>();
	List<Arc_T2P> ArcT2PSet = new ArrayList<Arc_T2P>();
	long[][] WeightMatrix = new long[100][100];
	FreeChoiceNet fcn=null;

/*	public void Register(Place p){
		if ( PlaceSet.contains(p) )
			throw new RuntimeException();			
		PlaceSet.add(p);
	}
	public void Register(Transition t){
		if ( TransitionSet.contains(t) )
			throw new RuntimeException();			
		TransitionSet.add(t);
	}
*/	public void Register(Arc_P2T arc){
		Place p = arc.GetPlace();
		Transition t = arc.GetTransition();
		if ( !PlaceSet.contains(p) || !TransitionSet.contains(t) )
			throw new RuntimeException();
		p.AddPostArc(arc);
		t.AddPreArc(arc);
		ArcP2TSet.add(arc);
		int pi = PlaceSet.indexOf(p), ti = TransitionSet.indexOf(t);
		this.WeightMatrix[pi][ti] = arc.GetWeight();
	}
	public void Register(Arc_T2P arc){
		Transition t = arc.GetTransition();
		Place p = arc.GetPlace();
		if ( !TransitionSet.contains(t) || !PlaceSet.contains(p) )
			throw new RuntimeException();
		t.AddPostArc(arc);
		p.AddPreArc(arc);
		ArcT2PSet.add(arc);
		int ti = TransitionSet.indexOf(t), pi = PlaceSet.indexOf(p);
		this.WeightMatrix[ti][pi] = arc.GetWeight();
	}
	
	public void UnRegister(Place p) {
		for (Arc_T2P arc : p.GetPreArcSet()) {
			arc.GetTransition().RemovePostArc(arc);
			ArcT2PSet.remove(arc);
		}
		for (Arc_P2T arc : p.GetPostArcSet()) {
			arc.GetTransition().RemovePreArc(arc);
			ArcP2TSet.remove(arc);
		}
		PlaceSet.remove(p);
		for (Place pt : PlaceSet) {
			pt.PlaceIndex = PlaceSet.indexOf(pt)+1;
		}
		for (Transition tt : TransitionSet) {
			tt.TransitionIndex = TransitionSet.indexOf(tt)+1;
		}
	}
	public void UnRegister(Transition t) {
		for (Arc_P2T arc : t.GetPreArcSet()) {
			arc.GetPlace().RemovePostArc(arc);
			ArcP2TSet.remove(arc);
		}
		for (Arc_T2P arc : t.GetPostArcSet()) {
			arc.GetPlace().RemovePreArc(arc);
			ArcT2PSet.remove(arc);
		}
		TransitionSet.remove(t);
		for (Place pt : PlaceSet) {
			pt.PlaceIndex = PlaceSet.indexOf(pt)+1;
		}
		for (Transition tt : TransitionSet) {
			tt.TransitionIndex = TransitionSet.indexOf(tt)+1;
		}
	}
	public void UnRegister(Arc_P2T arc) {
		arc.GetTransition().RemovePreArc(arc);
		arc.GetPlace().RemovePostArc(arc);
		ArcP2TSet.remove(arc);
	}
	public void UnRegister(Arc_T2P arc) {
		arc.GetTransition().RemovePostArc(arc);
		arc.GetPlace().RemovePreArc(arc);
		ArcT2PSet.remove(arc);
	}

	public String toString() {
		String ret = "";
		ret += "Number of Place: " + PlaceSet.size() + "\n";
		ret += "Marking now: ";
		for (Place p : PlaceSet) {
			ret += p.GetMarking() + " ";
		}
		ret += "\n";
		return ret;
	}
	public void Start() {
		for (Transition t : TransitionSet) {
			t.InvalidateOneStep();
			if (t.getState() == State.NEW)
				t.start();
			else
				t.SetStop(false);
		}
	}
	public void SetOneStep() {
		for (Transition t : TransitionSet) 
			t.OneStep();
	}
	public void Suspend() {
		for (Transition t : TransitionSet)
			t.SetStop(true);
	}
	
	public boolean CheckEFCN() {
		int m = PlaceSet.size();
		int n = TransitionSet.size();
		if (m == 0 && n == 0)
			return false;
		for (Place p : PlaceSet)
			if (p.GetMarking()>1)
				return false;
		int[][] FTS = new int[m][n], 
			FST = new int[m][n];
		int[] M = new int[m];
		for (Place p : PlaceSet)
			M[p.PlaceIndex-1] = (int)p.GetMarking();
		for (Arc_P2T p2t : ArcP2TSet)
			FST[p2t.GetPlace().PlaceIndex-1][p2t.GetTransition().TransitionIndex-1]
			                                 = (int)p2t.weight;
		for (Arc_T2P t2p : ArcT2PSet)
			FTS[t2p.GetPlace().PlaceIndex-1][t2p.GetTransition().TransitionIndex-1]
			                                 = (int)t2p.weight;
		fcn = new FreeChoiceNet(m,n,FTS,FST,M);
		return fcn.isEFCN();
	}
	
	public boolean CheckLivenessOfEFCN() {
		if (fcn==null && !CheckEFCN())
			throw new RuntimeException();
		return fcn.isLive()>0;
	}
}
